package com.maben.netty.udp;

import com.maben.netty.udp.handler.UdpServerHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;

/**
 * udp接收端
 */
@Component
public class NettyUdpServer {

    @Value("${netty.udp.port:8090}")
    private int port;

    @Resource
    private UdpServerHandler udpServerHandler;

    //事件循环，负责处理 Channel 上的 IO 事件和任务调度，每个 EventLoop 通常绑定一个线程。
    private EventLoopGroup group;

    private ChannelFuture channelFuture;

    /**
     * 启动UDP服务器
     */
    @PostConstruct
    public void start() throws InterruptedException {
        group = new NioEventLoopGroup(new DefaultThreadFactory("netty-udp-server"));

        //启动器，用于配置和启动 Netty 服务端
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioDatagramChannel.class) // 使用UDP通道
                .option(ChannelOption.SO_BROADCAST, true) // 支持广播
                .handler(new ChannelInitializer<NioDatagramChannel>() {
                    @Override
                    protected void initChannel(NioDatagramChannel ch) {
                        //pipeline:处理器链，由多个 ChannelHandler 组成，数据和事件会按顺序经过这些处理器
                        ch.pipeline().addLast(udpServerHandler);
                    }
                });

        // 绑定端口，启动服务器
        channelFuture = bootstrap.bind(port).sync();
        System.out.println(Thread.currentThread()+",UDP服务器已启动，监听端口: " + port);
    }

    /**
     * 停止UDP服务器
     */
    @PreDestroy
    public void stop() throws InterruptedException {
        if (channelFuture != null) {
            channelFuture.channel().close().sync();
        }
        if (group != null) {
            group.shutdownGracefully().sync();
        }
        System.out.println(Thread.currentThread()+",UDP服务器已停止");
    }
}
    